//
//  FFScrollPageView.swift
//  ZgwApp
//
//  Created by li on 2025-02-06.
//

import SwiftUI

struct FFScrollPageView<D: RandomAccessCollection, P: View>: View where D.Element: Hashable
{
	
	init(selected: Binding<D.Element?>, data: D, content: @escaping (D.Element) -> P) {
		self._selected = selected
		let datas = data.map({
			item in
			
			return FFLazyViewModel(data: item)
		})
		self._data = State(wrappedValue: datas)
		self.content = content
	}
	
	
	@Binding var selected: D.Element?
	@State var data: [FFLazyViewModel<D.Element>] = []
	/**
	 是否用户拖动
	 */
	@State private var isUserInteracting: Bool = false
	
	@ViewBuilder
	var content: (D.Element) -> P
	
	@State var offset: CGFloat = 0
	
	@State private var scrollPosition: FFScrollPosition = .init()
	@State var scrollViewModel = FFScrollViewModel().configure { objc in
		objc.scrollView.isPagingEnabled = true
	}
	var body: some View {
		GeometryReader { proxy in
//			ScrollViewReader { scroll in
				//				ScrollView(.horizontal) {
			FFScrollView(viewModel: scrollViewModel) {
					HStack(spacing: 0) {
						
						ForEach(data, id: \.self) { model in
							
							FFLazyView(data: model) { data in
								content(model.data)
							}
							.frame(width: proxy.size.width, height: proxy.size.height)
							.id(model.data)
						}
					}
//					.onGeometryChange(for: CGFloat.self, of: { geometry in
//						return geometry.frame(in: .scrollView).minX
//					}, action: { newValue in
//						
//						guard isUserInteracting else {
//							// 如果不是手动滑动,不触发下面的惰性处理,
//							return
//						}
//						
//						let next = newValue < offset ? true : false
//						
//						offset = newValue
//						let pageWidth = proxy.size.width
//						guard pageWidth > 0 else {
//							return
//						}
//						let index = abs(Int(newValue / pageWidth))
//						
//						let newIndex = next ?  index + 1 : index
//						
//						guard newIndex >= 0 && newIndex < data.count else {
//							return
//						}
//						
//						let model = data[newIndex]
//						if !model.viewDidLoad {
//							model.viewDidLoad = true
//						}
//					})
				}
//				.scrollTargetBehavior(.paging)
				.clipped()
//				.ffScrollPosition(position: $scrollPosition)
			
//				.onChange(of: selected, initial: true, { oldValue, newValue in
//
//				})
				.onFFChange(of: selected, initial: true, { oldValue, newValue in
					onChangeSelected(oldValue: oldValue, newValue: newValue, proxy: proxy)
				})
				.onFFScrollPhaseChange { oldValue, newValue, context in
					scrollPhaseChange(oldPhase: oldValue, newPhase: newValue, context: context, proxy: proxy)
				}
				.onFFScrollGeometryChange(for: CGFloat.self) { geomtery in
					return  geomtery.contentOffset.x
				} action: { oldValue, newValue in
					onScrollGeometryChange(oldeValue: oldValue, newValue: newValue, proxy: proxy)
				}

				
//			}
			//			.onScrollPhaseChange({ oldPhase, newPhase, context in
			//				print(oldPhase,newPhase)
			//				let x = context.geometry.contentOffset.x
			//
			//				if newPhase != oldPhase {
			//					if newPhase == .interacting ||  newPhase == .tracking {
			//						isUserInteracting = true
			//					}
			//
			//					if newPhase == .idle && isUserInteracting {
			//						let pageWidth = proxy.size.width
			//						let index = abs(Int(x / pageWidth))
			//
			//						guard index >= 0 && index < data.count else {
			//
			//							return
			//						}
			//
			//						let model = data[index]
			//						withAnimation {
			//							selected = model.data
			//						}
			//
			//						isUserInteracting = false
			//					}
			//				}
			//			})
		}
		.onAppear {
			print("tab appear")
		}
	}
	
	func scrollPhaseChange(oldPhase: FFScrollPhase, newPhase:  FFScrollPhase, context: FFScrollPhaseChangeContext, proxy: GeometryProxy) {
		let x = context.geometry.contentOffset.x
		
		if newPhase != oldPhase {
			if newPhase == .interacting ||  newPhase == .tracking {
				isUserInteracting = true
			}
			
			if newPhase == .idle && isUserInteracting {
				let pageWidth = proxy.size.width
				let index = abs(Int(x / pageWidth))
				
				guard index >= 0 && index < data.count else {
					
					return
				}
				
				let model = data[index]
				withAnimation {
					selected = model.data
				}
				
				isUserInteracting = false
			}
		}
	}
	
	func onScrollGeometryChange(oldeValue: CGFloat, newValue: CGFloat, proxy: GeometryProxy)  {
		guard isUserInteracting else {
			// 如果不是手动滑动,不触发下面的惰性处理,
			return
		}
		
		let next = newValue < offset ? true : false
		
		offset = newValue
		let pageWidth = proxy.size.width
		guard pageWidth > 0 else {
			return
		}
		let index = abs(Int(newValue / pageWidth))
		
		let newIndex = next ?  index + 1 : index
		
		guard newIndex >= 0 && newIndex < data.count else {
			return
		}
		
		let model = data[newIndex]
		if !model.viewDidLoad {
			model.viewDidLoad = true
		}
	}
	
	func onChangeSelected(oldValue: D.Element?, newValue: D.Element?, proxy: GeometryProxy)  {
		
		guard let model = data.first(where: {$0.data == newValue}) else {
			return
		}

		if !model.viewDidLoad {
			model.viewDidLoad = true
		}


		let width = proxy.size.width
		let index = data.firstIndex(where: {$0.data == newValue})?.advanced(by: 0)
		if let index {
			if oldValue == newValue {
				//						scroll.scrollTo(newValue)

//							scrollPosition.scrollTo(x: CGFloat(index) * width, y: 0, animated: false)
				scrollViewModel.scrollView.setContentOffset(CGPoint(x: CGFloat(index) * width, y: 0), animated: false)
			}else {
//							withAnimation {
//								scroll.scrollTo(newValue)
//							}
//							scrollPosition.scrollTo(x: CGFloat(index) * width, y: 0,
				scrollViewModel.scrollView.setContentOffset(CGPoint(x: CGFloat(index) * width, y: 0), animated: true)
			}
		}
	}
}

struct FFScrollPageTestView: View {
	
	@State var colors: [Color] = [.red, .green, .yellow, .gray, .black, .blue, .purple, .pink]
	@State var selected: Color? = .green
	var body: some View {
		VStack {
			
			Button {
				let random = colors.randomElement()
				
				
				selected = random
				
				
			} label: {
				Text("随机")
			}

			
			FFScrollPageView(selected: $selected, data: colors) {
				data in
				
				ZStack {
					data
					
					ScrollView {
						if #available(iOS 14.0, *) {
							LazyVStack {
								let max = Int.random(in: 200..<500)
								ForEach(0..<max, id: \.self) { index in
									Text("\(index)")
								}
							}
						} else {
							// Fallback on earlier versions
						}
					}
					
				}
				.onAppear {
//					print(data)
				}
			}
			.ffScrollViewPagingEnabled(true)
		}
		
	}
}
#Preview {
	FFScrollPageTestView()
}
